home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / PROGRAMM / PASCAL / 0189.ZIP / LOAN1.INC < prev    next >
Text File  |  1986-02-08  |  36KB  |  887 lines

  1.  
  2. const  ZERO        =  0;    { Used to clarify code.                     }
  3.        FILL_CHAR   = '_';   { Defines char. used to mark input fields.  }
  4.        SPACE       = ' ';   { Represents the ASCII space character, #32 }
  5.        NULL        = '';    { Represents a null string.                 }
  6.  
  7. { Output Control Characters }
  8.  
  9.        NUL         = #0;    { Null character.                }
  10.        BELL        = #7;    { Causes a beep when output to a }
  11.                             { terminal that has sound.       }
  12.        BS          = #8;    { Backspace.                     }
  13.        TAB         = #9;    { Tab character.                 }
  14.        LF          = #10;   { Line Feed.                     }
  15.        CR          = #13;   { Carriage Return.               }
  16.        FF          = #12;   { Form Feed.                     }
  17.        ESC         = #27;   { Escape character.              }
  18.        DEL         = #127;  { Del or Rubout character.       }
  19.  
  20. { Video Limits & Locations }
  21.  
  22.        MAX_ROW     = 24;      { Maximum number of rows for video.    }
  23.        MAX_COL     = 80;      { Maximum number of columns for video. }
  24.        MSG_LINE    = 22;      { Line to be used for user messages.   }
  25.        PROMPT_LINE = 23;      { Used for prompts, extended messages  }
  26.                               { and commands.                        }
  27.        CMD_LINE    = 24;      { Primary command input line.          }
  28.  
  29. { Input Control Keys:  Keyboard character code and video representation
  30.                        of keys used in Loan_Amortization application.
  31.                        Add others for general purpose use. The definitions
  32.                        shown will work on any Turbo supported system. The
  33.                        alternate definitions, which are commented out, will
  34.                        allow the IBM-PC and compatibles to use function and
  35.                        cursor control keys as indicated. }
  36.  
  37.  
  38.        BACKSP      = BS;           { Backspace or left arrow key.         }
  39. {      BS_KEY      = #32#17#196#196#32;    IBM-PC backspace key symbol.   }
  40.        BS_KEY      = ' <BkSpc> ';  { Use text appropriate for keyboard.   }
  41.        ENTER       = CR;           { Return or Enter key.                 }
  42. {      ENTER_KEY   = #32#17#196#217#32;    IBM-PC enter key symbol.       }
  43.        ENTER_KEY   = ' <Enter> ';  { Use text appropriate for keyboard.   }
  44.        CLEAR       = TAB;          { Forward tab key or ^I.               }
  45. {      CLEAR_KEY   = #32#196#196#16#221#32;   IBM-PC tab key symbol.      }
  46.        CLEAR_KEY   = ' <Tab> ';    { Use text appropriate for keyboard.   }
  47.        QUIT        = ESC;          { Escape key.                          }
  48.        QUIT_KEY    = ' <Esc> ';    { Use text appropriate for keyboard.   }
  49. {      PREV        = #72;            IBM up arrow key scan code.          }
  50. {      PREV_KEY    = #32#24#32;      IBM-PC up arrow symbol.              }
  51.        PREV        = ^E;           { Use code appropriate for key used.   }
  52.        PREV_KEY    = ' ^E ';       { Use text appropriate for keyboard.   }
  53. {      HELP        = #59;            IBM-PC F1 key scan code.             }
  54. {      HELP_KEY    = ' F1 ';         IBM-PC                               }
  55.        HELP        = ^A;           { Use code appropriate for key used.   }
  56.        HELP_KEY    = ' ^A ';       { Use text appropriate for keyboard.   }
  57.        LEAD_IN     = ESC;          { Lead in char. for IBM function keys. }
  58.                                    { Change as needed for other systems.  }
  59.  
  60. { String types:  General purpose string types. }
  61.  
  62. type   Str_5       = string[5];
  63.        Str_10      = string[10];
  64.        Str_15      = string[15];
  65.        Str_20      = string[20];
  66.        Str_30      = string[30];
  67.        Str_40      = string[40];
  68.        Str_60      = string[60];
  69.        Str_80      = string[80];
  70.        Str_255     = string[255];
  71.        File_ID     = string[64];
  72.        Drive_ID    = string[2];
  73.  
  74. { Set types: }
  75.  
  76.        Any_Char       = set of Char;       { Defined set of all characters.  }
  77.        Printable_Char = set of ' '..'~';   { Set of printable characters.    }
  78.        Special_Char   = set of #128..#255; { Set of Non-standard characters. }
  79.        Control_Char   = set of #0..#127;   { Set of Control characters. This }
  80.                                            { includes DEL and the IBM-PC     }
  81.                                            { function key scan codes.        }
  82.  
  83. var  default,                     { General purpose string buffer.         }
  84.      inp_str       : Str_255;     { Keyboard input string buffer.          }
  85.      i, j, k,                     { Misc. loop counter variables.          }
  86.      io_status     : Integer;     { Global status variable.                }
  87.      inctl,                       { Global control character.              }
  88.      inchr         : Char;        { Global input character.                }
  89.      output_id     : File_ID;     { Store ID of current output file/device.}
  90.      esc_flag,                    { Global logic control flags.            }
  91.      err_flag,
  92.      help_flag,
  93.      quit_flag,
  94.      end_session   : Boolean;
  95.  
  96.  
  97. { Additional global constants types and variables required for data
  98.   input and display routines. }
  99.  
  100. const  MAX_FLD     = 32;  { Set maximum number of input fields permitted. }
  101.  
  102. { Field input type codes. }
  103.  
  104.        TEXT_FLD    = 'T'; { Text field. Used for screen doc. only. }
  105.        UC_TEXT     = 'U'; { Upper Case text field.                 }
  106.        NUMERIC     = 'N'; { Numeric field.                         }
  107.  
  108. { Field exit type codes. }
  109.  
  110.        REQUIRED    = 'R'; { Identifies field that requires an entry.       }
  111.        PROTECTED   = 'P'; { Identifies a field to be skipped during input. }
  112.        MANUAL      = 'M'; { Manual exit field. User must press <CR>.       }
  113.        AUTOMATIC   = 'A'; { Automatic exit after last char. is entered.    }
  114.  
  115.        INCR        = 1;     { INCR & DECR are used to set the }
  116.        DECR        = -1;    { direction indicator variable.   }
  117.  
  118. { Define data structure to hold input field parameters. }
  119.  
  120. type   Fld_Parms   = record
  121.                        xloc        : Integer;  { Video column.              }
  122.                        yloc        : Integer;  { Video row.                 }
  123.                        fld_len     : Integer;  { Maximum field length.      }
  124.                        fld_type    : Char;     { See input constants above. }
  125.                        exit_type   : Char;     { See exit constants above.  }
  126.                        fld_msg     : Str_60;   { User prompt message.       }
  127.                      end;
  128.  
  129. { Define data structure to hold text for video screens. }
  130.  
  131.        Scrn        = array[1..MAX_ROW] of Str_80;
  132.  
  133. { Define an array of field parameter records. }
  134.  
  135.        Inp_Parms   = array[1..MAX_FLD] of Fld_Parms; { Input field parameters. }
  136.  
  137. { Define pointer and record for help screen text. }
  138.  
  139.        Help_Pointer = ^Help_Text;
  140.  
  141.        Help_Text    = record
  142.                         help_txt   : Str_80;
  143.                         next_line  : Help_Pointer;
  144.                       end;
  145.  
  146. { Global variables used by standard input and display routines. }
  147.  
  148. var  fld_cnt,                  { Holds number of fields on current screen. }
  149.      direction     : Integer;  { Increment/Decrement indicator.            }
  150.      top_of_heap   : ^Integer; { Dummy pointer for use by Mark & Release.  }
  151.      first_help    : Help_Pointer; { Pointer to first line of help text.   }
  152.  
  153.  
  154. { Forward declaration of error handling routines which use some of the
  155.   routines in the STD-UTIL.INC file and are also used by some of these
  156.   routines. }
  157.  
  158.     procedure Disp_IO_Error(device_name: File_ID); forward;
  159.  
  160.     procedure Disp_Error_Msg(err_msg: Str_80); forward;
  161.  
  162.     procedure Beep;
  163.       begin
  164.         Write(BELL);  { Use this statement for non-IBM-PC systems.         }
  165. (*      begin         { This routine may be substituted on IBM-PC systems. }
  166.           Sound(440); Delay(250); NoSound;
  167.         end;                                                              *)
  168.       end; { Beep }
  169.  
  170.     procedure Repeat_Char(character : Char;     { Character to be output.    }
  171.                           count     : Integer); { Number of times to output. }
  172.       var i     : Integer;
  173.  
  174.       begin
  175.         i := ZERO;
  176.         while (i < count) do
  177.           begin
  178.             Write(character);
  179.             i := Succ(i);
  180.           end;
  181.       end; { Repeat_Char }
  182.  
  183.     procedure Strip_Trailing_Char(var inp_str : Str_255; { String to strip.}
  184.                                       len     : Byte;    { Maximum length. }
  185.                                       strip   : Char);   { Char. to strip. }
  186.  
  187.   { Scan inp_str from len downto 0 until a character <> strip is found.
  188.     Set the length of inp_str equal to the position of the character
  189.     found if any. Note that inp_str is set to null if it contains only
  190.     strip characters. }
  191.  
  192.       begin
  193.         inp_str[0] := Chr(0);       { Set inp_str length byte to ZERO. }
  194.         while (inp_str[len] = strip) and (len > ZERO) do
  195.           len := Pred(len);
  196.         inp_str[0] := Chr(len);     { Set inp_str length to len. }
  197.       end; { Strip_Trailing_Char }
  198.  
  199.     procedure Strip_Leading_Char(var inp_str : Str_255; { String to strip. }
  200.                                      len     : Byte;    { Maximum length.  }
  201.                                      strip   : Char);   { Char. to strip.  }
  202.  
  203.       var  i         : Byte;
  204.  
  205.   { Find the first occurrence, if any, of a character not equal to strip.
  206.     Copy the remainder of inp_str into the new inp_str. Note inp_str is set
  207.     to null if it is null initially or it contains only strip characters. }
  208.  
  209.       begin
  210.         i := 1;
  211.         While (inp_str[i] = strip) and (i <= len) do
  212.           i := Succ(i);
  213.         inp_str := Copy(inp_str,i,len);
  214.       end; { Strip_Leading_Char }
  215.  
  216.  
  217.     function Stripped(inp_str : Str_255;        { String to strip. }
  218.                       len     : Byte;           { Maximum length.  }
  219.                       strip   : Char): Str_255; { Char. to strip.  }
  220.  
  221. { Uses procedures defined above to strip leading and trailing
  222.   occurances of the character strip from inp_str. }
  223.  
  224.       begin
  225.         Strip_Trailing_Char(inp_str,len,strip);
  226.         Strip_Leading_Char(inp_str,len,strip);
  227.         Stripped := inp_str;
  228.       end; { Stripped }
  229.  
  230.   function Exist(file_name: File_ID): Boolean;
  231.     var chk_file  : File;
  232.  
  233.     begin
  234.       Assign(chk_file,file_name);
  235. {$I-} Reset(chk_file); {$I+}
  236.       Exist := (IOresult = ZERO);
  237. {$I-} Close(chk_file); io_status := IOresult; {$I+}
  238.     end; { Exist }
  239.  
  240.     procedure Read_Kbd(var inchr,inctl: Char);
  241.  
  242. {    Keyboard input routine that will allow users of systems with
  243.      `IBM-PC type' function keys to use those keys as control keys.
  244.      It will also work on systems using standard control keys producing
  245.      ASCII characters #1..#31 & #127. The variable parameters will
  246.      be set as follows depending on the key that is pressed.
  247.  
  248.      inchr  will contain the character value of the key pressed.
  249.             If a control/function key is pressed this will be the
  250.             `lead in' value for the key, if any.  For example the
  251.             lead in character for function keys on many systems is the
  252.             escape character, ASCII #27.
  253.      inctl  will contain NUL or a control/function key value which may be
  254.             used to determine whether a control/function key was pressed
  255.             and if so which key it was. }
  256.  
  257.       begin
  258.         inctl := NUL;                    { Initialize to inctl to NUL.    }
  259.         Read(Kbd,inchr);                 { Wait for a key to be pressed.  }
  260.         if (KeyPressed and (inchr = LEAD_IN)) then
  261.           begin                          { Get function key scan code.    }
  262.             Delay(0);                    { Increase Delay if needed.      }
  263.             Read(Kbd,inctl);             { Scan code goes in inctl.       }
  264.           end
  265.         else
  266.           if (inchr in [#1..#31,DEL]) then
  267.             inctl := inchr;              { Trap conventional control chrs.}
  268.       end; { Read_Kbd }
  269.  
  270.   function Valid_Key(valid_keys: Any_Char): Char;
  271.     var inchr, inctl : Char;
  272.  
  273. { Waits for a key to be pressed that is a member of the set valid_keys.
  274.   The ASCII value of the key is returned. Non-control keys are
  275.   displayed. A beep is sounded for invalid keys.
  276.  
  277.   Note that alpha characters are forced to upper case. }
  278.  
  279.      begin
  280.        repeat
  281.          Read_Kbd(inchr,inctl);        { Wait for a key to be pressed. }
  282.          if (inctl = NUL) then
  283.            begin                       { If it is not a control key    }
  284.              inchr := UpCase(inchr);   { force it to upper case and    }
  285.              Write(inchr,BS);          { display it, restoring cursor. }
  286.            end
  287.          else                          { If it is a control key then   }
  288.            inchr := inctl;             { pass it through for testing.  }
  289.          if (not (inchr in valid_keys)) then
  290.            Beep;                       { Beep if it's not valid.       }
  291.        until (inchr in valid_keys);
  292.        Valid_Key := inchr;             { Return the valid character.   }
  293.      end; { Valid_Key }
  294.  
  295.   procedure Init_Field (init_char : Char;
  296.                         var parms : Fld_Parms);
  297.     var  i   : Byte;
  298.  
  299. { Initialize field with init_char based on parms.
  300.   Parameters are:
  301.  
  302.   init_char  Fill character to be used for field initialization.
  303.   parms      Input field parameters for the field to be initialized. }
  304.  
  305.     begin
  306.       with parms do
  307.       begin
  308.         GoToXY(xloc,yloc);                { Position cursor. }
  309.         Repeat_Char(init_char,fld_len);   { Init field with init_char. }
  310.         GoToXY(xloc,yloc);                { Restore cursor position. }
  311.       end;
  312.     end; { Init_Field }
  313.  
  314.   procedure Get_Field_Input(var parms    : Fld_Parms;
  315.                             var chr_set  : Printable_Char;
  316.                             var ctrl_set : Control_Char);
  317.  
  318.     var   count  : Integer; { Number of characters entered. }
  319.           exit   : Boolean; { Local exit flag.              }
  320.  
  321. { General purpose keyboard input routine.
  322.   Parameters are:
  323.   parms      Input field parameters for the field to be processed.
  324.   chr_set    Set of characters acceptable for input. Beep for others.
  325.   ctrl_set   Set of control/fuction characters acceptable for input. }
  326.  
  327. { Global variables used:
  328.          esc_flag    Boolean   Global exit flag.
  329.          inp_str     Str_255   Input buffer string. Note that
  330.                                Length(inp_str) is set to count on exit.
  331.          direction   Integer   Increment/Decrement indicator. Switched to
  332.                                DECR if valid control character is PREV.
  333.          inchr       Char      Used to store input character.
  334.          inctl       Char      Used to store input control/function code. }
  335.  
  336.     procedure Process_Control_Character;
  337.       var i  : Byte;
  338.  
  339.   { Select action based on control key pressed by user. }
  340.  
  341.   { Global variables used:
  342.            esc_flag  : Boolean;  Used to indicate that QUIT key pressed.
  343.            help_flag : Boolean;  Used to indicate that HELP key pressed.
  344.            direction : Integer;  Increment/Decrement indicator. }
  345.  
  346.       procedure Backspace(fill: Char);
  347.  
  348.     { Perform destructive backspace on video and remove last character
  349.       from inp_str. The parameter is:
  350.  
  351.       fill   Character to be output in place of character deleted. }
  352.  
  353.         begin
  354.           if (count > ZERO) then
  355.             begin
  356.               Write(BS,fill,BS);     { Destructive backspace to video.     }
  357.               count := Pred(count);  { Decrement characters entered count. }
  358.             end
  359.           else
  360.             Beep;                    { Beep if count = ZERO initially.     }
  361.         end; { Backspace }
  362.  
  363.       procedure Clear_Field;
  364.         var i : Byte;
  365.  
  366.     { Initialize video field and clear input string. }
  367.  
  368.         begin
  369.           Init_Field(FILL_CHAR,parms);           { Clear video field. }
  370.           with parms do
  371.             FillChar(inp_str,fld_len + 1,ZERO);  { Clear inp_str. }
  372.           count := ZERO;                         { Reset count to ZERO. }
  373.         end; { Clear_Field }
  374.  
  375.       begin { Process_Control_Character }
  376.         case inctl of
  377.             BACKSP  : Backspace(FILL_CHAR);
  378.             ENTER   : exit := TRUE;
  379.             QUIT    : begin
  380.                         esc_flag := TRUE;
  381.                         exit := TRUE;
  382.                       end;
  383.             PREV    : begin
  384.                         Clear_Field;
  385.                         direction := DECR;
  386.                         exit := TRUE;
  387.                       end;
  388.             CLEAR   : begin
  389.                         Clear_Field;
  390.                         exit := TRUE;
  391.                       end;
  392.             HELP    : begin
  393.                         help_flag := TRUE;
  394.                         exit := TRUE;
  395.                       end;
  396.             else      Beep;
  397.         end; {case}
  398.       end; { Process_Control_Character }
  399.  
  400.     procedure Accept_Valid_Character;
  401.  
  402.   { If inchr is a member of chr_set and that the field length has
  403.     not been exceeded, display inchr, increment count
  404.     and store the character in inp_str; otherwise Beep.
  405.     If the end of an AUTOMATIC exit field is reached set the exit
  406.     flag and indicate that a CR has been received by setting inctl to CR. }
  407.  
  408.       begin
  409.         with parms do
  410.         begin
  411.           if (fld_type = UC_TEXT) then
  412.             inchr := UpCase(inchr);
  413.           if (inchr in chr_set) and (count < fld_len) then
  414.             begin
  415.               Write(inchr);
  416.               count := Succ(count);
  417.               inp_str[count] := inchr;
  418.               if (exit_type = AUTOMATIC) and (count = fld_len) then
  419.                 begin
  420.                   exit := TRUE; inctl := CR;
  421.                 end;
  422.             end
  423.           else
  424.             Beep;
  425.         end;
  426.       end; { Accept_Valid_Character }
  427.  
  428.     begin { Get_Field_Input }
  429.       count := ZERO;
  430.       esc_flag := FALSE; exit := FALSE;
  431.       direction := INCR;
  432.       repeat
  433.         Read_Kbd(inchr,inctl);
  434.         if (inctl in ctrl_set) then
  435.           Process_Control_Character
  436.         else
  437.           Accept_Valid_Character;
  438.       until exit;
  439.       inp_str[0] := Chr(count);             { Set length of input string.  }
  440.       Repeat_Char(SPACE,(parms.fld_len - count)); { Clear to end of field. }
  441.     end; { Get_Field_Input }
  442.  
  443.   function Valid_Str(var parms: Fld_Parms): Str_80;
  444.  
  445.     const chr_set     : Printable_Char = [SPACE..'~'];
  446.           ctrl_set    : Control_Char   = [CR,BS,CLEAR,PREV,QUIT];
  447.  
  448. { Accepts field input based on parms. If the user presses <CR> without
  449.   entering anything, the value of the global default string is returned.
  450.   Otherwise the characters entered, up to the maximum indicated by
  451.   parms.fld_len, are returned as a string. }
  452.  
  453.     begin
  454.       Valid_Str := default;    { Returns default if no value is entered. }
  455.       Get_Field_Input(parms,chr_set,ctrl_set);
  456.       if ((inctl = CR) and (Length(inp_str) > ZERO)) or
  457.          (inctl = CLEAR) then
  458.         Valid_Str := inp_str;
  459.     end; { Valid_Str }
  460.  
  461.   function Valid_Real(var parms   : Fld_Parms;
  462.                           point   : Byte;
  463.                           min,max : Real): Real;
  464.  
  465.     const chr_set     : Printable_Char = ['0'..'9','-','.'];
  466.           ctrl_set    : Control_Char   = [CR,BS,CLEAR,PREV,QUIT];
  467.  
  468.     var   real_val    : Real;
  469.           min_str,
  470.           max_str     : Str_20;
  471.           err_msg     : Str_80;
  472.  
  473. { Accepts field input based on parms. If the user presses <CR> without
  474.   entering anything, the Real value of the global default string is returned.
  475.   Otherwise the string entered is converted to a Real value. If the value
  476.   is not in the range indicated by min and max or a there is an error in
  477.   the conversion, an error message is displayed. }
  478.  
  479.     begin { Valid_Real }
  480.       Val(Stripped(default,Length(default),SPACE),real_val,io_status);
  481.       if io_status <> ZERO then  { If default is a bad numeric value      }
  482.         real_val := 0.0;         { then return 0.0.                       }
  483.       Valid_Real := real_val;    { Return default if no value is entered. }
  484.       Get_Field_Input(parms,chr_set,ctrl_set);
  485.       if ((inctl = CR) and (Length(inp_str) > ZERO)) or
  486.          (inctl = CLEAR) then
  487.         begin
  488.           if (inctl = CLEAR) then
  489.             inp_str := '0.00';
  490.           Val(inp_str,real_val,io_status);
  491.           if (io_status = ZERO) and
  492.              ((real_val >= min) and (real_val <= max)) then
  493.             Valid_Real := real_val
  494.           else
  495.             begin
  496.               Str(min:parms.fld_len:point,min_str); { The point parameter    }
  497.               Str(max:parms.fld_len:point,max_str); { indicates the position }
  498.               err_msg := 'Value must be from '      { of the decimal point.  }
  499.                           + min_str + ' through ' + max_str;
  500.               Disp_Error_Msg(err_msg);
  501.               direction := ZERO;            { Force re-entry of field. }
  502.             end;
  503.         end;
  504.     end; { Valid_Real}
  505.  
  506.   function Valid_Int(var parms   : Fld_Parms;
  507.                          min,max : Integer): Integer;
  508.  
  509.     const chr_set     : Printable_Char = ['0'..'9','-'];
  510.           ctrl_set    : Control_Char   = [CR,BS,CLEAR,PREV,QUIT];
  511.  
  512.     var   int_val     : Integer;
  513.           min_str,
  514.           max_str     : Str_20;
  515.           err_msg     : Str_80;
  516.  
  517. { Accepts field input based on parms. If the user presses <CR> without
  518.   entering anything, the Integer value of the global default string is returned.
  519.   Otherwise the string entered is converted to an Integer value. If the value
  520.   is not in the range indicated by min and max or a there is an error in
  521.   the conversion, an error message is displayed. }
  522.  
  523.     begin { Valid_Int }
  524.       Val(Stripped(default,Length(default),SPACE),int_val,io_status);
  525.       if io_status <> ZERO then { If default is a bad numeric value      }
  526.         int_val := ZERO;        { then return ZERO.                      }
  527.       Valid_Int := int_val;     { Return default if no value is entered. }
  528.       Get_Field_Input(parms,chr_set,ctrl_set);
  529.       if ((inctl = CR) and (Length(inp_str) > ZERO)) or
  530.          (inctl = CLEAR) then
  531.         begin
  532.           if (inctl = CLEAR) then
  533.             inp_str := '0';
  534.           Val(inp_str,int_val,io_status);
  535.           if (io_status = ZERO) and
  536.              ((int_val >= min) and (int_val <= max)) then
  537.             Valid_Int := int_val
  538.           else
  539.             begin
  540.               Str(min:parms.fld_len,min_str);
  541.               Str(max:parms.fld_len,max_str);
  542.               err_msg := 'Value must be from ' + min_str +
  543.                          ' through ' + max_str;
  544.               Disp_Error_Msg(err_msg);
  545.               direction := ZERO;             { Forces re-entry of field. }
  546.             end;
  547.         end;
  548.     end; { Valid_Int }
  549.  
  550.   function Valid_Chr(var parms     : Fld_Parms;
  551.                          valid_set : Printable_Char): Char;
  552.  
  553.     const ctrl_set : Control_Char  = [CR,BS,CLEAR,PREV,QUIT];
  554.  
  555. { Accepts field input based on parms. If the user presses <CR> without
  556.   entering anything, the first character of the global default string is
  557.   returned. Otherwise the user must enter a character that is a member of
  558.   the valid_set parameter. }
  559.  
  560.     begin  { Valid_Chr }
  561.       Valid_Chr := default[1]; { Returns default if no value is entered. }
  562.       Get_Field_Input(parms,valid_set,ctrl_set);
  563.       if ((inctl = CR) and (Length(inp_str) > ZERO)) or
  564.          (inctl = CLEAR) then
  565.         Valid_Chr := inp_str[1]
  566.     end; { Valid_Chr }
  567.  
  568.    procedure Clr_Eol(line: Byte);
  569.      var blank_line : Str_80;
  570.  
  571. { Alternate clear to end of line routine for systems that scroll the
  572.   video screen when a Turbo ClrEol is executed on the 24th line.
  573. }
  574.      begin
  575.        FillChar(blank_line,81,SPACE); blank_line[0] := Chr(79);
  576.        GoToXY(1,line); Write(blank_line);
  577.        GoToXY(1,line);
  578.      end; { Clr_Eol }
  579.  
  580.    procedure Clear_Prompts;
  581.  
  582.  { Clears the prompt area as defined by the global constants used. }
  583.  
  584.      begin
  585.        GoToXY(1,MSG_LINE); ClrEol;
  586.        GoToXY(1,PROMPT_LINE); ClrEol;
  587.        GoToXY(1,CMD_LINE); Clr_Eol(CMD_LINE); { Systems with 25 video lines }
  588.      end; { Clear_Prompts }                   { can use ClrEol.             }
  589.  
  590.    procedure Display_Prompt(line    : Byte;
  591.                             prompt  : Str_10;
  592.                             msg_str : Str_80);
  593.  
  594. {  Displays prompt & highlighted msg_str at line.
  595.    Parameters are:
  596.    line     The video line on which the prompt and msg_str are displayed.
  597.    prompt   A string that identifies the nature of the message.
  598.    msg_str  The message to be displayed.
  599.  
  600.    Note: The calling routine must preserve and restore the cursor position
  601.          and video intensity as needed.
  602.          Combined length of prompt & msg_str should be less than 76.
  603. }
  604.     begin { Display_Prompt }
  605.       GoToXY(1,line); Clr_Eol(line);  { Systems with 25 video lines }
  606.       LowVideo;                       { can use ClrEol. }
  607.       Write(Prompt,': '); NormVideo;
  608.       Write(msg_str);
  609.     end; { Display_Prompt }
  610.  
  611.   procedure Disp_Error_Msg; { (err_msg: Str_80); }
  612.     var  inchr : Char;      { forward defined in STD-UTIL.PAS }
  613.  
  614. { Displays err_msg at MSG_LINE and a `continue prompt' at PROMPT_LINE.
  615.   Clears both lines when user presses any key.
  616.  
  617.   Note: The calling routine must preserve and restore cursor position and
  618.         video intensity as well as the contents of the MSG_LINE & PROMPT_LINE. }
  619.  
  620.     begin
  621.       Display_Prompt(MSG_LINE,'ERR',err_msg); GoToXY(1,PROMPT_LINE);
  622.       Display_Prompt(PROMPT_LINE,
  623.                        'MSG','Press ANY KEY to try again. ==> ');
  624.       Beep;
  625.       Read(Kbd,inchr);                  { Pause until key is pressed }
  626.       GoToXY(1,MSG_LINE); ClrEol; GoToXY(1,PROMPT_LINE); ClrEol;
  627.     end; { Disp_Error_Msg }
  628.  
  629.   procedure Disp_IO_Error;   { (device_name: File_ID); }
  630.                              { forward defined in STD-UTIL.PAS }
  631.     var IO_Msg     : Str_80;
  632.         err_str    : string[3];
  633.         valid_keys : Printable_Char;
  634.  
  635.  { Converts global io_status to a text error message combined with its
  636.    device_name parameter. Displays error message and sets global error_flag. }
  637.  
  638.     begin
  639.       case io_status of
  640.         $01  :  IO_Msg := 'not found';
  641.         $02  :  IO_Msg := 'not open for input';
  642.         $03  :  IO_Msg := 'not open for output';
  643.         $04  :  IO_Msg := 'not open';
  644.         $05  :  IO_Msg := 'not readable';
  645.         $06  :  IO_Msg := 'not Assigned. Unable to Write';
  646.         $10  :  IO_Msg := 'recieved bad numeric data';
  647.         $20  :  IO_Msg := 'not able to perform operation requested';
  648.         $21  :  IO_Msg := 'not available in Memory mode';
  649.         $22  :  IO_Msg := 'not available for Assign statement';
  650.         $90  :  IO_Msg := 'does not contain matching record type';
  651.         $91  :  IO_Msg := 'does not contain record requested';
  652.         $99  :  IO_Msg := 'end encountered unexpectedly';
  653.         $F0  :  IO_Msg := 'cannot be written to';
  654.         $F1  :  IO_Msg := 'cannot be written due to full Directory';
  655.         $F2  :  IO_Msg := 'has exceeded the maximum file size';
  656.         $FF  :  IO_Msg := 'is no longer on the current disk';
  657.       else      begin
  658.                   Str(io_status:3,err_str);
  659.                   IO_Msg := 'has experienced I/O error:' + err_str;
  660.                 end;
  661.       end; {case}
  662.       Clear_Prompts;
  663.       IO_Msg := 'Device/File ' + device_name + ' ' + IO_Msg;
  664.       Display_Prompt(PROMPT_LINE,'MSG',IO_Msg);
  665.       Display_Prompt(CMD_LINE,'CMD','Ignore |  Abort');
  666.       Display_Prompt(MSG_LINE,'INP',
  667.                       'Press CMD: key to enter selection. (I/A) ==> ');
  668.       if (Valid_Key(['A','I']) = 'A') then
  669.         err_flag := TRUE
  670.       else
  671.         io_status := ZERO;
  672.     end; { Disp_IO_Error }
  673.  
  674.   procedure Load_SCR_File(file_name     : File_ID;
  675.                           var text_buf  : Scrn;
  676.                           var text_file : Text);
  677.     var line_cnt : Byte;
  678.  
  679. { Loads up to MAX_ROW lines of text from text_file into text_buf.
  680.   if text file contains more than MAX_ROW lines of text, io_status 
  681.   is set to MAX_ROW + 1. Any other value of io_status greater than 0
  682.   should be treated as an I/O error. It is left to the calling routine
  683.   to handle such errors.
  684.   Text_file is left open so that the calling routine may Read additional
  685.   text if necessary. The caller is responsible for closing text_file. }
  686.  
  687.     begin
  688.       Assign(text_file,file_name);
  689. {$I-}
  690.       Reset(text_file); io_status := IOresult;
  691.       line_cnt := 1;
  692.       While (io_status = ZERO) and (not Eof(text_file)) do
  693.         if line_cnt > MAX_ROW then
  694.           io_status := line_cnt
  695.         else
  696.           begin
  697.             ReadLn(text_file,text_buf[line_cnt]);
  698.             io_status := IOresult;
  699.             if (io_status = ZERO) then
  700.               line_cnt := Succ(line_cnt)
  701.             else
  702.               Disp_IO_Error(file_name);
  703.           end;
  704. {$I+}
  705.     end; { Load_SCR_File }
  706.  
  707.   procedure Load_Input_Scrn(scrn_id       : File_ID;
  708.                             var scrn_text : Scrn;
  709.                             var fld_dat   : Inp_Parms);
  710.  
  711.     type Txt_Num             = string[2];
  712.  
  713.     var  scrn_file           : Text;
  714.          txt_x, txt_y,
  715.          txt_cnt, txt_len    : Txt_Num;
  716.          i                   : Byte;
  717.          dummy               : Char;
  718.  
  719. { Loads the screen text from file identified by scrn_id into the
  720.   screen buffer pointed to by scrn_text. The input field parameters
  721.   are then loaded into the fld_dat array. }
  722.  
  723.     procedure Read_Field_Parameters;
  724.       var status : array[1..10] of Integer;  { Used for error trapping. }
  725.  
  726. {   Reads parameters for fld_cnt fields into fld_dat parameter array.
  727.     The format of the parameter in scrn_file must be a follows:
  728.  
  729.     n1,n2,n3,X,Y,Msg
  730.  
  731.     n1  = 2 digit video screen row of input field.
  732.     n2  = 2 digit video screen col of input field.
  733.     n3  = 2 digit length in characters of input field.
  734.     X   = 1 character field type as defined in global constants.
  735.     Y   = 1 character field exit type as defined in global constants.
  736.     Msg = Up to 60 characters, followed by End Of Line. }
  737.  
  738.       procedure Check_Status;
  739.         begin
  740.           i := 1;                         { Set up loop to check status }
  741.           while (i < 11) do
  742.             if (status[i] <> ZERO) then
  743.               begin                      { If error encountered, display }
  744.                 io_status := status[i];  { error message and exit loop. }
  745.                 Disp_IO_Error(scrn_id);
  746.                 i := 11;
  747.               end
  748.             else
  749.               i := Succ(i);
  750.         end; { Check_Status }
  751.  
  752.       begin  { Read_Field_Parameters }
  753.         for i := 1 to fld_cnt do
  754.           With fld_dat[i] do
  755.           begin
  756. {$I-}
  757.             Read(scrn_file,txt_y,dummy); status[1] := IOresult;
  758.             Read(scrn_file,txt_x,dummy); status[2] := IOresult;
  759.             Read(scrn_file,txt_len,dummy); status[3] := IOresult;
  760.             Read(scrn_file,fld_type,dummy); status[4] := IOresult;
  761.             Read(scrn_file,exit_type,dummy); status[5] := IOresult;
  762.             ReadLn(scrn_file,fld_msg); status[6] := IOresult;
  763.             Val(txt_x,xloc,io_status); status[7] := io_status;
  764.             Val(txt_y,yloc,io_status); status[8] := io_status;
  765.             Val(txt_len,fld_len,io_status); status[9] := io_status;
  766.           end;
  767.           Close(scrn_file); status[10] := IOresult;
  768. {$I+}
  769.           Check_Status; { Display first error encountered & set error_flag. }
  770.       end; { Read_Field_Parameters }
  771.  
  772.     begin { Load_Input_Scrn }
  773.       Load_SCR_File(scrn_id,scrn_text,scrn_file); { Load screen text.      }
  774.       if (io_status = (MAX_ROW + 1)) then
  775.         begin
  776. {$I+}
  777.           ReadLn(scrn_file,txt_cnt);              { Read number of fields. }
  778.           io_status := IOresult;
  779. {$I-}
  780.           if (io_status = ZERO) then
  781.             Val(txt_cnt,fld_cnt,io_status);    { Convert fld_cnt to number.}
  782.           if (io_status = ZERO) then
  783.             Read_Field_Parameters
  784.           else
  785.             begin
  786.               Disp_Error_Msg('Conversion error in screen file.');
  787.               err_flag := TRUE;
  788.             end;
  789.         end
  790.           else
  791.             begin
  792.               Disp_Error_Msg('Invalid input screen file.');
  793.               err_flag := TRUE;
  794.             end;
  795.     end { Load_Input_Scrn };
  796.  
  797.   procedure Disp_Input_Scrn(inp_scrn: Scrn);
  798.     var  i   : Byte;
  799.  
  800. { Writes text from inp_scrn screen text buffer to video. }
  801.  
  802.     begin
  803.       NormVideo;
  804.       for i := 1 to 4 do WriteLn(inp_scrn[i]);
  805.       LowVideo;
  806.       for i := 5 to (MAX_ROW -1) do
  807.          WriteLn(inp_scrn[i]);
  808.       Write(inp_scrn[MAX_ROW]); { Required to prevent scrolling on systems }
  809.       NormVideo;                { with MAX_ROW video lines. }
  810.     end { Disp_Input_Scrn };
  811.  
  812.     procedure Load_Help_Text(file_name: File_ID);
  813.       const MIN_HEAP = $800;  { Leave at least 2K free on the heap. }
  814.  
  815.       var help_file : Text;
  816.           new_line,
  817.           last_line : Help_Pointer;
  818.  
  819.       begin
  820.         Mark(top_of_heap);
  821.         first_help := nil;
  822.         Assign(help_file,file_name);
  823. {$I-}
  824.         Reset(help_file); io_status := IOresult;
  825.           while ((not Eof(help_file)) and (MemAvail > MIN_HEAP)) and
  826.                 (io_status = ZERO) do
  827.             begin
  828.               New(new_line);
  829.               ReadLn(help_file,new_line^.help_txt);
  830.               io_status := IOresult;
  831.               if (first_help = nil) then
  832.                 first_help := new_line
  833.               else
  834.                 last_line^.next_line := new_line;
  835.               last_line := new_line;
  836.               last_line^.next_line := nil;
  837.             end;
  838. {$I+}
  839.           if (io_status <> ZERO) then
  840.             Disp_IO_Error(file_name);
  841.           if (MemAvail <= MIN_HEAP) then
  842.             Disp_Error_Msg('Insufficient memory for complete help file');
  843.       end; { Load_Help_Text }
  844.  
  845.   procedure Disp_Help(first, last: Integer);
  846.      var line_ptr  : Help_Pointer;
  847.          line_cnt  : Integer;
  848.  
  849. { Displays `help screen' information from dynamic memory. The information
  850.   displayed is determined by first and last, which refer to line numbers
  851.   in help_file. Information is displayed starting at row 1 with a dashed
  852.   line followed by (last - first + 1) lines of help text and ends on row
  853.   (last - first + 3) which is another dashed line.
  854.  
  855.   Note: The calling routine must preserve and restore screen contents.
  856.         Last - first should be less than 20. }
  857.  
  858.     begin
  859.       GoToXY(1,1); Repeat_Char('-',(MAX_COL - 1)); WriteLn;
  860.       line_ptr := first_help;
  861.       line_cnt := 1;
  862.       while (line_cnt < first) and (line_ptr <> nil) do
  863.         begin
  864.           line_ptr := line_ptr^.next_line;
  865.           line_cnt := Succ(line_cnt);
  866.         end;
  867.       while (line_cnt <= last) and (line_ptr <> nil) do
  868.         begin
  869.           ClrEol;
  870.           WriteLn(line_ptr^.help_txt);
  871.           line_ptr := line_ptr^.next_line;
  872.           line_cnt := Succ(line_cnt);
  873.         end;
  874.       Repeat_Char('-',(MAX_COL - 1));
  875.       Clear_Prompts;
  876.       Display_Prompt(MSG_LINE,'MSG','Press ANY KEY to continue... ');
  877.       Read(Kbd,inchr);
  878.     end; { Disp_Help }
  879.  
  880.     procedure Verify_Exit;
  881.       begin
  882.         Display_Prompt(MSG_LINE,'INP','Do you want to END this session? (Y/N) ==> ');
  883.         if (Valid_Key(['Y','N']) = 'Y') then
  884.           end_session := TRUE;
  885.       end; { Verify_Exit }
  886.  
  887.